package com.feishi.core.util.common;



import com.feishi.core.util.common.bean.CallBack;

import java.io.*;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;

/**
 * @version 1.0
 * @auth caixq
 * @time 18-1-30 15:08
 **/
public class CmdUtil {

    private static ExecutorService service;
    public static void main(String[] args) throws IOException {
        String cmd = "/home/caixq/anaconda2/bin/mavproxy.py --out=udpin:0.0.0.0:14550";
        CommandWrapper interactive = CmdUtil.run(cmd
                , client -> System.out.println("recieveMsg::" + client.msg)
        );
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String str = reader.readLine();
            if ("exit".equals(str)) {
                interactive.close();
                break;
            }
            interactive.sendCmd(str);
        }
    }

    public static CommandWrapper run(String cmd) throws IOException {
        return run(cmd, null, null);
    }

    public static CommandWrapper run(String cmd, CallBack<CommandWrapper> callBack) throws IOException {
        return run(cmd, callBack, null);
    }

    public static CommandWrapper run(String[] cmd) throws IOException {
        return run(cmd, null, null);
    }

    public static CommandWrapper run(String[] cmd, CallBack<CommandWrapper> callBack) throws IOException {
        return run(cmd, callBack, null);
    }

    public static CommandWrapper run(String cmd, CallBack<CommandWrapper> callBack, ExecutorService service) throws IOException {

        return run(new String[]{cmd}, callBack, service);
    }

    public static CommandWrapper run(String[] cmds, CallBack<CommandWrapper> callBack, ExecutorService service) throws IOException {
        Process ps = cmds.length == 1 ? Runtime.getRuntime().exec(cmds[0]) : Runtime.getRuntime().exec(cmds);
        BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
        OutputStream out = ps.getOutputStream();
        ps.getErrorStream();
        CommandWrapper interactive = new CommandWrapper(out);

        if (callBack != null) {
            if (service == null) {
                if(CmdUtil.service==null){
                    CmdUtil.service=ThreadUtil.newCachedThreadPool();
                }
                service = CmdUtil.service;
            }
            service.execute(() -> {
                while (ps.isAlive()){
                    try {
                        while (br.ready()) {
                            interactive.msg = br.readLine();
                            callBack.execute(interactive);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            });
        }
        interactive.ps = ps;
        return interactive;
    }

    public static class CommandWrapper {
        public String msg;
        public OutputStream out;
        public Thread in;
        public Process ps;

        public CommandWrapper(OutputStream out) {
            this.out = out;
        }

        public void close() {
            ps.destroy();
        }

        public void sendCmd(String str) {
            write(str + "\n");
        }

        private void write(String str) {
            try {
                out.write((str).getBytes());
                Method method = BufferedOutputStream.class.getDeclaredMethod("flushBuffer");
                method.setAccessible(true);
                method.invoke(out);
//                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
